﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
using CircleDrawer;
using CircleDrawer.Shapes;

namespace ShapeDrawer
{
    public class DrawingPane : Canvas
    {
        private bool inDraw;
        private IDeletable lastShape;
        private Point lastPoint;
        public int zoomLevel;
        
        public Uri SavedAtUri;

        public bool IsSaved
        {
            get
            {
                if (this.SavedAtUri != null)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }

        public DrawingPane(int width, int height)
        {
            this.Width = width;
            this.Height = height;
            this.Background = new SolidColorBrush(Colors.White);

            this.MouseLeftButtonDown += Canvas_MouseLeftButtonDown;
            this.MouseMove += Canvas_MouseMove;
            this.MouseLeftButtonUp += Canvas_MouseLeftButtonUp;
            this.MouseRightButtonUp += DrawingPane_MouseRightButtonUp;
            this.ClipToBounds = true;
            this.inDraw = false;
            this.zoomLevel = 1;
        }

        void DrawingPane_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (ShapeDrawing.Mode == DrawingMode.Zoom)
            {
                ZoomOut();
            }
        }

        void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.inDraw = false;
            this.lastShape = null;

            if (ShapeDrawing.Mode == DrawingMode.Zoom)
            {
                ZoomIn(e.GetPosition(this).X, e.GetPosition(this).Y);
            }
        }

        void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.inDraw)
            {
                Draw();
            }
        }

        void Canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            this.inDraw = true;
            this.lastPoint = Mouse.GetPosition(this);
        }

        public void Draw()
        {
            if (ShapeDrawing.Mode == DrawingMode.Ellipse)
            {
                DrawEllipse();
            }
            else if (ShapeDrawing.Mode == DrawingMode.Polygon)
            {
                DrawPolygon();
            }
        }

        private void DrawEllipse()
        {
            if (this.lastShape != null)
            {
                this.lastShape.Delete();
            }

            EllipseSD ellipse = new EllipseSD();
            Point mouse = Mouse.GetPosition(this);
            
            double width = mouse.X - lastPoint.X;
            ellipse.Width = Math.Abs(width);
            double height = mouse.Y - lastPoint.Y;
            ellipse.Height = Math.Abs(height);

            if (width > 0 && height > 0)
            {
                ellipse.Margin = new Thickness(lastPoint.X, lastPoint.Y, 0, 0);
            }
            else if (width > 0 && height < 0)
            {
                ellipse.Margin = new Thickness(lastPoint.X, mouse.Y, 0, 0);
            }
            else if (width < 0 && height < 0)
            {
                ellipse.Margin = new Thickness(mouse.X, mouse.Y, 0, 0);
            }
            else if (width < 0 && height > 0)
            {
                ellipse.Margin = new Thickness(mouse.X, lastPoint.Y, 0, 0);
            }

            SolidColorBrush mySolidColorBrush = new SolidColorBrush();

            ellipse.StrokeThickness = 1;
            ellipse.Stroke = Brushes.Black;

            ellipse.DrawIn(this);
            this.lastShape = ellipse;
        }

        private void DrawPolygon()
        {
            if (this.lastShape != null)
            {
                this.lastShape.Delete();
            }

            Point mouse = Mouse.GetPosition(this);
            double hexagonCenterX = (lastPoint.X + mouse.X) / 2;
            double hexagonCenterY = (lastPoint.Y + mouse.Y) / 2;

            PointCollection hexagonPoints = new PointCollection();

            double hexWidth = Math.Abs(mouse.X - lastPoint.X);
            double hexHeight = Math.Abs(mouse.Y - lastPoint.Y);

            Point leftTop = new Point(hexagonCenterX - hexWidth/4, hexagonCenterY - hexHeight/2);
            Point rightTop = new Point(hexagonCenterX + hexWidth/4, hexagonCenterY - hexHeight/2);
            Point rightMiddle = new Point(hexagonCenterX + hexWidth / 2, hexagonCenterY);
            Point rightBot = new Point(hexagonCenterX + hexWidth / 4, hexagonCenterY + hexHeight / 2);
            Point leftBot = new Point(hexagonCenterX - hexWidth/4, hexagonCenterY + hexHeight/2);
            Point leftMiddle = new Point(hexagonCenterX - hexWidth/2, hexagonCenterY);

            HexagonSD hexagon = new HexagonSD();
            hexagon.AddPoint(leftTop);
            hexagon.AddPoint(rightTop);
            hexagon.AddPoint(rightMiddle);
            hexagon.AddPoint(rightBot);
            hexagon.AddPoint(leftBot);
            hexagon.AddPoint(leftMiddle);

            hexagon.StrokeThickness = 1;
            hexagon.Stroke = Brushes.Black;

            hexagon.DrawIn(this);
            this.lastShape = hexagon;
        }

        private void ZoomIn(double mouseX, double mouseY)
        {
            this.zoomLevel *= 2;
            this.LayoutTransform = new ScaleTransform(this.zoomLevel, this.zoomLevel, mouseX, mouseY);
        }

        private void ZoomOut()
        {
            this.zoomLevel /= 2;
            if (this.zoomLevel < 1)
            {
                this.zoomLevel = 1;
            }
            this.LayoutTransform = new ScaleTransform(this.zoomLevel, this.zoomLevel);
        }

        public void MarkAsSaved(Uri saveAtUri)
        {
            this.SavedAtUri = saveAtUri;
        }

        public DrawingPane Clone()
        {
            DrawingPane clonedPane = new DrawingPane((int)this.Width, (int)this.Height);
            clonedPane.inDraw = this.inDraw;
            clonedPane.lastPoint = new Point();
            clonedPane.lastPoint.X = this.lastPoint.X;
            clonedPane.lastPoint.Y = this.lastPoint.Y;

            foreach (UIElement item in this.Children)
            {
                UIElement cloning = CloneThroughXml.Clone<UIElement>(item);

                if (cloning.GetType() == typeof(Image))
                {
                    ((Image)cloning).Source = ((Image)item).Source;
                }

                clonedPane.Children.Add(cloning);
            }

            return clonedPane;
        }
    }
}
